#include "pch.h"
#include "Effects.h"
#include "DXOthers/d3dUtil.h"
#include "EffectHelper.h"	
#include "DXOthers/DXTrace.h"
#include "RenderStates.h"
using namespace DirectX;

class DebugEffect::Impl :public  AlignedType<DebugEffect::Impl>
{
public:
	struct CBPerDebug
	{
		XMMATRIX world;
// 		int i;
// 		int pad[3];
	};
public:
	Impl() {};
	~Impl() = default;
	CBufferObject<0, CBPerDebug> m_pBuffer;

	ComPtr<ID3D11VertexShader> m_pVS;
	ComPtr<ID3D11PixelShader> m_pPS;

	ComPtr<ID3D11InputLayout> m_pPosInputLayout;

	int currentIdx = -1;	//	表明当前正在进行哪一个Debug，
	ID3D11ShaderResourceView** mDebugTexs;
};


DebugEffect::DebugEffect()
{
	pImpl = std::make_unique<Impl>();
}
DebugEffect::~DebugEffect()
{

}

DebugEffect& DebugEffect::Get()
{
	static DebugEffect* lightEffect = new DebugEffect();
	return *lightEffect;
}

bool DebugEffect::InitAll(ID3D11Device* device)
{
	if (device == nullptr)
		return false;

	if (!RenderStates::IsInit())
		RenderStates::InitAll(device);

	ComPtr<ID3DBlob> blob;
	// 创建顶点着色器
	HR(CreateShaderFromFile(L"..\\GDX11Renderer\\HLSL\\Debug\\DebugVS.cso", L"..\\GDX11Renderer\\HLSL\\DebugVS.hlsl", "VS", "vs_5_0", blob.ReleaseAndGetAddressOf()));
	HR(device->CreateVertexShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, pImpl->m_pVS.GetAddressOf()));
	// 创建顶点布局
	HR(device->CreateInputLayout(GDxVertex::VertexPosNormalTangentTex, ARRAYSIZE(GDxVertex::VertexPosNormalTangentTex),
		blob->GetBufferPointer(), blob->GetBufferSize(), pImpl->m_pPosInputLayout.GetAddressOf()));

	// 创建像素着色器
	HR(CreateShaderFromFile(L"..\\GDX11Renderer\\HLSL\\Debug\\DebugPS.cso", L"..\\GDX11Renderer\\HLSL\\DebugPS.hlsl", "PS", "ps_5_0", blob.ReleaseAndGetAddressOf()));
	HR(device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, pImpl->m_pPS.GetAddressOf()));


	HR(pImpl->m_pBuffer.CreateBuffer(device));

	D3D11SetDebugObjectName(pImpl->m_pPosInputLayout.Get(), "VertexPosLayout");
	D3D11SetDebugObjectName(pImpl->m_pBuffer.cBuffer.Get(), "CBPerDebug");
	D3D11SetDebugObjectName(pImpl->m_pVS.Get(), "DebugVS");
	D3D11SetDebugObjectName(pImpl->m_pPS.Get(), "DebugPS");

	return true;
}

void DebugEffect::SetRenderDefault(ID3D11DeviceContext* deviceContext)
{
	deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	deviceContext->IASetInputLayout(pImpl->m_pPosInputLayout.Get());
	deviceContext->VSSetShader(pImpl->m_pVS.Get(), nullptr, 0);
	deviceContext->GSSetShader(nullptr, nullptr, 0);
	deviceContext->RSSetState(nullptr);
	deviceContext->PSSetShader(pImpl->m_pPS.Get(), nullptr, 0);
	deviceContext->OMSetDepthStencilState(RenderStates::DSSNoDepthTest.Get(),0);
	deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF);
}

void DebugEffect::SetTexture(ID3D11ShaderResourceView** texture)
{
	pImpl->mDebugTexs = texture;
}

void XM_CALLCONV DebugEffect::SetWorldMatrix(DirectX::FXMMATRIX W)
{
	static int i = 0;
	i %= NUM_GBUFFER;
	pImpl->currentIdx = i++;

	auto& cBuffer = pImpl->m_pBuffer;
	cBuffer.data.world = XMMatrixTranspose(W);
	cBuffer.isDirty = true;
}


void DebugEffect::Apply(ID3D11DeviceContext* deviceContext)
{
	pImpl->m_pBuffer.BindVS(deviceContext);

	pImpl->m_pBuffer.UpdateBuffer(deviceContext);

	deviceContext->PSSetShaderResources(0, 1, &pImpl->mDebugTexs[pImpl->currentIdx]);
}
